package com.example.spring5.IOC;

import com.example.spring5.bean.*;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IOC_Bean {

    public static void main(String[] args) {
        /**
         * 1、在 Spring 里面，设置创建 bean 实例是单实例还是多实例
         * 2、在 Spring 里面，默认情况下，bean 是单实例对象
         *
         */
        IOC依赖注入调用();

    }

    private static void 工厂Bean() {
        /**
         * IOC 操作 Bean 管理（FactoryBean）
         * 1、Spring 有两种类型 bean，一种普通 bean，另外一种工厂 bean（FactoryBean）
         * 2、普通 bean：在配置文件中定义 bean 类型就是返回类型
         * 3、工厂 bean：在配置文件定义 bean 类型可以和返回类型不一样
         *   第一步 创建类，让这个类作为工厂 bean，实现接口 FactoryBean
         *   第二步 实现接口里面的方法，在实现的方法中定义返回的 bean 类型
         *
         * 工厂 bean
         */
        ApplicationContext a2 = new ClassPathXmlApplicationContext("IOC.xml");

        UserDao mybean = a2.getBean("myBean", UserDao.class);//工厂 bean
        mybean.add();
    }

    private static void IOC依赖注入调用() {

        /**
         * 2、Bean 管理操作有两种方式
         *  （1）基于 xml 配置文件方式实现
         *  （2）基于注解方式实现
         * 普通 bean
         *
         * 基于 xml 方式注入属性
         *   什么是DI机制？
         *   依赖注入（Dependency Injection）和控制反转（Inversion of Control）是同一个概念，
         *   具体的讲：当某个角色需要另外一个角色协助的时候，在传统的程序设计过程中，
         *   通常由调用者来创建被调用者的实例。但在spring中创建被调用者的工作不再由调用者来完成，
         *   因此称为控制反转。创建被调用者的工作由spring来完成，然后注入调用者因此也称为依赖注入。
         *   spring以动态灵活的方式来管理对象 ，
         *        注入的两种方式，设置注入和构造注入。
         *            设置注入的优点：直观，自然
         *            构造注入的优点：可以在构造器中决定依赖关系的顺序。
         *
         */
        UserDao u = new UserDao();
//        u.setUserName("666");//1.set注入
        UserDao u1 = new UserDao("555");//2.有参构造注入

        //3.通过xml的set注入
        ApplicationContext a1 = new ClassPathXmlApplicationContext("IOC.xml");
        UserDao userDao = a1.getBean("userDao", UserDao.class);
        System.out.println(userDao.getUserName());//

        //4.通过xml的有参构造注入
        UserDao userDao1 = a1.getBean("userDao01", UserDao.class);
        System.out.println(userDao1.getUserName());//
        //5.p名称空间的xml的set获取
        UserDao userDao2 = a1.getBean("userDao02", UserDao.class);
        System.out.println(userDao2.getUserName());//
        //6.p名称空间的xml的有参构造注入
        UserDao userDao3 = a1.getBean("userDao03", UserDao.class);
        System.out.println(userDao3.getUserName());//

        //等等 看    "IOC.xml"

        User user = a1.getBean("user05", User.class);
        System.out.println(user.toString());//.

        Pet p = a1.getBean("pet03",Pet.class);
        System.out.println(p.getName());//特殊符号编写
    }
}
//工厂bean
class MyBean implements FactoryBean<UserDao> { //设置了MyBean返回的对象是UserDao对象

    @Override //定义返回类型
    public UserDao getObject() throws Exception {
        return new UserDao("555");
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
